#include <iostream>
#include <vector>
#include <stdio.h>

template <int deminsion>
class Chess
{
private:
    std::vector<std::vector<int>> board;
    int player;
    int gameover;
    int playerJustMoved;
    /* data */
public:
    Chess(/* args */)
    {
        for (int i = 0; i < deminsion; i++)
        {
            std::vector<int> row(deminsion, 1);
            board.push_back(row);
        };
        playerJustMoved = 1;
        player = 3 - playerJustMoved;
        gameover = 0;
    }
    ~Chess(){};
    /**
     * @brief Create a deep clone of this game state.
     *
     * @return Chess
     */
    Chess clone()
    {
        Chess<deminsion> st;
        st.player = this->player;
        st.gameover = this->gameover;
        st.playerJustMoved = this->playerJustMoved;
        st.board.clear();
        for (int i = 0; i < deminsion; i++)
        {
            std::vector<int> row_new;
            row_new.assign(board[i].begin(), board[i].end());
            st.board.push_back(row_new);
        };
        return st;
    }

    bool IsGameOver()
    {
        return gameover == 1;
    }

    /**
     * @brief 检查一个move是否合规
     *
     * @param move const std::pair<int, int>
     * @return std::vector<std::pair<int, int>> ：如果合规，返回需要提取的棋子的坐标，不合规则返回空vector
     */
    std::vector<std::pair<int, int>> checkMove(const std::pair<int, int> move)
    {
        std::vector<std::pair<int, int>> indexs;
        int i = move.first - 1;
        int j = move.second - 1;
        if (i > j)
        {
            return indexs;
        }
        int m1 = i / deminsion;
        int n1 = i % deminsion;
        int m2 = j / deminsion;
        int n2 = j % deminsion;

        if (m1 != m2 && n1 != n2)
        {
            return indexs;
        }
        else
        {
            m2 += 1;
            n2 += 1;
            int flag = 0;

            for (int ii = m1; ii < m2; ii++)
            {
                for (int jj = n1; jj < n2; jj++)
                {
                    if (board[ii][jj] == 0)
                    {
                        indexs.clear();
                        flag = 1;
                        break;
                    }
                    else
                    {
                        indexs.push_back({ii, jj});
                    }
                }
                if (flag)
                {
                    break;
                }
            }
        }
        return indexs;
    }

    /**
     * @brief       进行一步操作，输入为一个数组，数组中第一个数是第一个棋子坐标，第二个数是第二个棋子坐标。move[0] <= move[2].
        以4*4为例，坐标值分别为：
        1  2  3  4
        5  6  7  8
        9  10 11 12
        13 14 15 16
     *
     * @param move
     */
    void DoMove(const std::pair<int, int> move)
    {
        if (gameover == 1)
            return;
        auto indexs = checkMove(move);
        if (indexs.size() == 0)
        {
            printf("Illegal input :  [%d, %d]", move.first, move.second);
            return;
        }

        for (int i = 0; i < indexs.size(); i++)
        {
            auto index = indexs[i];
            board[index.first][index.second] = 0;
        }
        playerJustMoved = player;
        player = 3 - player;
        int chess_on_board_num = 0;
        for (int i = 0; i < deminsion; i++)
        {
            for (int j = 0; j < deminsion; j++)
            {
                chess_on_board_num += board[i][j];
            }
        }

        if (chess_on_board_num == 0)
        {
            gameover = 1;
        }
    }

    /**
     * @brief 获得所有可行操作
     *
     * @return std::vector<std::pair<int, int>>
     */
    std::vector<std::pair<int, int>> GetMoves()
    {
        std::vector<std::pair<int, int>> moves;
        for (int i = 1; i < deminsion * deminsion + 1; i++)
        {
            for (int j = i; j < deminsion * deminsion + 1; j++)
            {
                std::pair<int, int> move(i, j);
                if (checkMove({i, j}).size() > 0)
                {
                    moves.push_back(move);
                }
            }
        }
        return moves;
    }

    int GetResult(int player_id)
    {
        if (player_id == 1 || player_id == 2)
        {
            if (playerJustMoved == player_id)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }
        else
        {
            return -1;
        }
    }

    /**
     * @brief 打印当前棋盘
     *
     * @param
     */
    void PrintBoard()
    {
        printf("\n--------------\n");
        for (int i = 0; i < deminsion; i++)
        {
            printf("|");
            for (int j = 0; j < deminsion; j++)
            {
                printf("%2d ", (i * deminsion + j + 1) * board[i][j]);
            }
            printf("|\n");
        }
        printf("--------------\n");
    }
};

void PrintMoves(std::vector<std::pair<int, int>> *moves)
{
    for (int i = 0; i < moves->size(); i++)
    {
        if (i % 5 == 0)
        {
            printf("\n");
        }
        auto move = moves->at(i);
        printf("[%2d, %2d] ", move.first, move.second);
    }
}

int main()
{
    Chess<4> game;
    game.PrintBoard();
    //  1  2  3  4
    //  5  6  7  8
    //  9 10 11 12
    // 13 14 15 16
    auto available_moves = game.GetMoves(); // 获得所有可行的动作
    PrintMoves(&available_moves);
    game.DoMove({2, 10}); // 进行一步可执行动作
    game.PrintBoard();
    game.DoMove({2, 3}); // 进行一步非法动作
    game.PrintBoard();   // 打印棋盘，可以看出程序不会执行动作
    game.DoMove({1, 1}); // 进行一系列动作
    game.DoMove({4, 16});
    game.DoMove({5, 13});
    game.DoMove({3, 15});

    game.PrintBoard();

    auto game2 = game.clone(); //clone game -> game2
    game.DoMove({14, 14});
    game.PrintBoard();
    game2.PrintBoard();      // game2 不会跟随game 变化

    std::cout << game.IsGameOver() << std::endl;
    std::cout << game.GetResult(2) << std::endl;
    std::cout << game.GetResult(1) << std::endl;
    return 0;
}
